﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using DG.Tweening;


public class GameController : MonoSingleton<GameController> {

	public GameObject agentPrefab;
	public GameObject mainMenuUI;
	public GameObject gameUI;
	public AudioSource sfxPlayer;

	public Agent[] agents { get; protected set; }
	public StartPoint[] startPoints { get; protected set; }
	public FinishPoint[] finishPoints { get; protected set; }
	public WavePoint[] waves { get; protected set; }

	public bool isPlaying { get; protected set; }

	public void playSFX (AudioClip clip) {
		sfxPlayer.PlayOneShot(clip);
	}

	protected void LevelFail (IEvent eventData) {
		if (isPlaying == true) {
			Log("LEVEL FAIL");

			if (gameUI != null)
				gameUI.SetActive(false);

			isPlaying = false;

			playSFX(Resources.Load<AudioClip>("Sound/lose"));

			Invoke("LevelReset", 2f);
		}
	}

	protected void LevelSuccess (IEvent eventData) {
		if (isPlaying == true) {
			Log("LEVEL SUCCESS");

			int arrivedCount = 0;
			for (int i = 0; i < agents.Length; i++) {
				var agent = agents[i];
				if (agent.arrived == true)
					arrivedCount++;
			}

			if (arrivedCount == agents.Length) {
				if (gameUI != null)
					gameUI.SetActive(false);

				isPlaying = false;

				playSFX(Resources.Load<AudioClip>("Sound/win"));

				Invoke("GotoNextLevel", 2f);
			}
		}
	}

	protected void LevelLoaded (Scene level, LoadSceneMode loadSceneMode) {
		Log("LEVEL LOADED");

		isPlaying = false;

		Invoke("LevelReset", 1f);
	}

	public void LevelReset () {
		startPoints = FindObjectsOfType<StartPoint>();
		finishPoints = FindObjectsOfType<FinishPoint>();
		waves = FindObjectsOfType<WavePoint>();

		if (waves != null) {
			for (int i = 0; i < waves.Length; i++) {
				var wave = waves[i];
				wave.Reset();
			}
		}

		if (agents != null) {
			for (int i = 0; i < agents.Length; i++) {
				var agent = agents[i];
				agent.Sink();
			}
			agents = null;
		}

		if (startPoints != null && startPoints.Length > 0) {
			agents = new Agent[startPoints.Length];

			for (int i = 0; i < startPoints.Length; i++) {
				var startPoint = startPoints[i];

				var agentGO = GameObject.Instantiate(agentPrefab) as GameObject;
				var agent = agentGO.GetComponent<Agent>();

				agent.Reset();
				agent.transform.position = startPoint.transform.position;

				agents[i] = agent;
			}

			if (gameUI != null) {
				gameUI.SetActive(true);

				if (!string.IsNullOrEmpty(startPoints[0].levelName)) {
					var levelNameText = gameUI.transform.Find("LevelName").GetComponent<Text>();
					levelNameText.text = startPoints[0].levelName;

					levelNameText.enabled = true;
					levelNameText.rectTransform.anchoredPosition = new Vector2(0f, -30f);
					levelNameText.color = new Color(1f, 1f, 1f, 0f);
					var sequence = DOTween.Sequence();
					sequence.Append(levelNameText.rectTransform.DOAnchorPosY(0f, 1f));
					sequence.Insert(0f, levelNameText.DOFade(1f, 1f));
					sequence.AppendInterval(1.5f);
					sequence.Append(levelNameText.rectTransform.DOAnchorPosY(30f, 1f));
					sequence.Insert(2.5f, levelNameText.DOFade(0f, 1f));
					sequence.OnComplete(() => {
						levelNameText.enabled = false;
					});
				}
			}

			isPlaying = true;

			Log("PLAYING");
		}
	}

	public void GotoNextLevel () {
		Log("GO TO NEXT LEVEL");

		if (finishPoints != null && 
			finishPoints.Length > 0 && 
			!string.IsNullOrEmpty(finishPoints[0].nextLevelName)) {
			SceneManager.LoadScene(finishPoints[0].nextLevelName, LoadSceneMode.Single);

			if (mainMenuUI != null)
				mainMenuUI.SetActive(false);
		}

		agents = null;
		startPoints = null;
		finishPoints = null;
		waves = null;
	}

	void Start () {
		Input.multiTouchEnabled = false;

		EventDispatchCenter.getInstance().addEventListener("level_fail", LevelFail);
		EventDispatchCenter.getInstance().addEventListener("level_success", LevelSuccess);

		SceneManager.sceneLoaded += LevelLoaded;

		if (gameUI != null)
			GameObject.DontDestroyOnLoad(gameUI);
		if (mainMenuUI != null)
			GameObject.DontDestroyOnLoad(mainMenuUI);

		LevelReset();
	}

	protected override void OnDestroy ()
	{
		base.OnDestroy();

		SceneManager.sceneLoaded -= LevelLoaded;
	}

	protected static void Log(string message) {
		Debug.Log(message);
	}

}
